package com.egao.common.module.company.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.net.Ipv4Util;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.CreditCodeUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.egao.common.component.minio.config.MinioBucket;
import com.egao.common.component.minio.service.MinioService;
import com.egao.common.core.Constants;
import com.egao.common.core.exception.BusinessException;
import com.egao.common.core.exception.ParameterException;
import com.egao.common.core.utils.RegexUtil;
import com.egao.common.core.web.JsonResult;
import com.egao.common.core.web.PageParam;
import com.egao.common.manage.CommonRefService;
import com.egao.common.module.company.constants.CheckRecordConstants;
import com.egao.common.module.company.constants.CompanyConstants;
import com.egao.common.module.company.entity.Company;
import com.egao.common.module.company.entity.CompanyCheckRecord;
import com.egao.common.module.company.entity.vo.CompanyForgotFormVO;
import com.egao.common.module.company.entity.vo.CompanyFormVO;
import com.egao.common.module.company.entity.vo.CompanyFromCodeVo;
import com.egao.common.module.company.entity.vo.CompanyListVO;
import com.egao.common.module.company.mapper.CompanyMapper;
import com.egao.common.module.company.service.CompanyCheckRecordService;
import com.egao.common.module.company.service.CompanyService;
import com.egao.common.module.company.utils.CompanyUtil;
import com.egao.common.module.system.constants.EmailConstants;
import com.egao.common.module.system.entity.Dict;
import com.egao.common.module.system.entity.OperRecord;
import com.egao.common.module.system.entity.User;
import com.egao.common.module.system.entity.UserRole;
import com.egao.common.module.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用人单位(Company)表服务实现类
 *
 * @author dl
 */
@Service
@Slf4j
public class CompanyServiceImpl extends ServiceImpl<CompanyMapper, Company> implements CompanyService {

    @Autowired
    private DictService dictService;

    @Autowired
    private UserService userService;

    @Autowired
    private EmailService emailService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private OperRecordService operRecordService;

    @Autowired
    private MinioService minioService;

    @Autowired
    private CommonRefService commonRefService;


    @Autowired
    private CompanyCheckRecordService companyCheckRecordService;

    @Override
    public List<CompanyListVO> listPage(PageParam<CompanyListVO> page) {
        //申请时间
        page = (PageParam<CompanyListVO>) CompanyUtil.putApplyTime(page);
        return baseMapper.listPage(page);
    }

    @Override
    public JsonResult detail(Integer id) {
        Company company = verifyCompany(id);

        Integer userId = company.getUserId();
        if (userId == null) {
            throw new ParameterException("单位用户编号为空");
        }

        User user = userService.getById(userId);
        if (user == null) {
            throw new BusinessException("单位用户不存在");
        }

        company.setUserName(user.getUsername());

        String businessUrl = company.getBusinessUrl();
        String businessUrlPreview = minioService.getPreSignedObjectUrl(MinioBucket.MINIO_COMPANY, businessUrl);
        company.setBusinessUrlPreview(businessUrlPreview);

        String legalPersons = company.getLegalPersons();
        String legalPersonsPreview = minioService.getPreSignedObjectUrl(MinioBucket.MINIO_COMPANY, legalPersons);
        company.setLegalPersonsPreview(legalPersonsPreview);

        return JsonResult.ok().setData(getDetail(company));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult checkCompany(CompanyFormVO companyFormVO) {
        if (companyFormVO == null) {
            throw new ParameterException("单位为空");
        }

        Company company = baseMapper.selectById(companyFormVO.getId());
        if (company == null) {
            throw new BusinessException("单位不存在");
        }

        // 是否需要修改用户单位名称
        boolean isCompanyNameState = false;
        if (!companyFormVO.getName().equals(company.getName())) {
            isCompanyNameState = true;
        }

        BeanUtil.copyProperties(companyFormVO, company);

        //判断用户名是否修改
        User oldUser = userService.getById(company.getUserId());
        if (oldUser == null) {
            throw new BusinessException("单位用户不存在");
        }

        //是否需要修改用户登录名
        boolean isUpdateUserName = false;
        if (!oldUser.getUsername().equals(company.getUserName())) {
            if (userService.getUserIsExistByUserName(company.getUserName())) {
                throw new BusinessException("账号已存在");
            }
            isUpdateUserName = true;
            oldUser.setUsername(company.getUserName());
        }
        //是否需要修改用户密码
        boolean isUpdatePassword = false;
        if (company.getPassword() != null) {
            oldUser.setPassword(userService.encodePsw(company.getPassword()));
            isUpdatePassword = true;
        }
        //是否需要修改用户状态
        boolean isUpdateState = false;
        //单位状态为锁定并且单位用户账号为正常需要修改为锁定
        if (CompanyConstants.COMPANY_STATE_LOCK.equals(company.getState()) && CompanyConstants.NO_FOUND_COMPANY.equals(oldUser.getState())) {
            oldUser.setState(CompanyConstants.SUCCESS_COMPANY);
            isUpdateState = true;
        }

        //单位状态不是锁定并且单位用户账号为锁定需要修改为正常
        if (!CompanyConstants.COMPANY_STATE_LOCK.equals(company.getState()) && CompanyConstants.SUCCESS_COMPANY.equals(oldUser.getState())) {
            oldUser.setState(CompanyConstants.NO_FOUND_COMPANY);
            isUpdateState = true;
        }

        if (updateById(company)) {
            if (isUpdateUserName || isUpdatePassword || isUpdateState || isCompanyNameState) {
                oldUser.setName(company.getName());
                userService.updateById(oldUser);
            }
            userRoleService.deleteRole(oldUser.getUserId());
            UserRole userRole = new UserRole();
            if (CompanyConstants.COMPANY_STATE_PASS.equals(company.getState())) {
                // 审核通过
                userRole.setRoleId(4);
            } else {
                // 其他状态
                userRole.setRoleId(7);
            }
            userRole.setUserId(oldUser.getUserId());
            userRoleService.save(userRole);
            CompanyCheckRecord companyCheckRecord = new CompanyCheckRecord();
            companyCheckRecord.setCompanyId(company.getId());
            companyCheckRecord.setState(company.getState());
            companyCheckRecord.setStateContent(company.getStateContent());
            companyCheckRecord.setCheckUserId(companyFormVO.getCheckUserId());
            companyCheckRecord.setType(CheckRecordConstants.CHECK_COMPANY);
            companyCheckRecord.setBusinessId(company.getId());
            companyCheckRecordService.save(companyCheckRecord);

            //需要发送邮件通知
            if (CompanyConstants.SUCCESS.equals(company.getEmailFlag())) {
                //发送邮件
                String[] email = {company.getUserName()};
                emailService.sendTextEmail(EmailConstants.TITLE_COMPANY_CHECK, company.getStateContent(), email);
            }

            return JsonResult.ok("提交成功");
        }
        return JsonResult.error("提交失败");
    }

    @Override
    public JsonResult getCompanyDict() {
        Map<String, Object> map = new HashMap<>(CompanyConstants.MAP_INIT);

        //获取单位行业
        List<Dict> natureList = dictService.cacheNatureList(CompanyConstants.NATURE_LIST_TYPE);
        map.put("natureList", natureList);

        //获取单位行业
        List<Dict> industryList = dictService.cacheList(CompanyConstants.INDUSTRY_LIST_TYPE);
        map.put("industryList", industryList);

        //获取单位规模
        List<Dict> scaleList = dictService.cacheList(CompanyConstants.SCALE_LIST_TYPE);
        map.put("scaleList", scaleList);

        return JsonResult.ok("查询成功").setData(map);
    }

    @Override
    public JsonResult updateRecruitFlag(Integer id) {
        Company company = verifyCompany(id);

        //修改单篇状态，如果之前为0改为1
        if (CompanyConstants.SUCCESS.equals(company.getRecruitFlag())) {
            company.setRecruitFlag(CompanyConstants.FAILED);
        } else {
            company.setRecruitFlag(CompanyConstants.SUCCESS);
        }

        if (updateById(company)) {
            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult deleteFlag(Integer id, Integer deleted, Integer userId) {
        if (id == null) {
            throw new ParameterException("单位编号为空");
        }

        if (deleted == null) {
            throw new ParameterException("单位状态为空");
        }

        if (userId == null) {
            throw new ParameterException("单位账号为空");
        }

        //修改单篇状态，如果之前为0改为1
        if (CompanyConstants.SUCCESS_COMPANY.equals(deleted)) {
            deleted = CompanyConstants.NO_FOUND_COMPANY;
        } else {
            deleted = CompanyConstants.SUCCESS_COMPANY;
        }

        if (baseMapper.updateCompanyDeleted(deleted, id) == 1 && userService.updateUserDeleted(deleted, userId) == 1) {
            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    @Override
    public Company getCompanyByOrganizationCode(String organizationCode) {
        if (StrUtil.isBlank(organizationCode)) {
            return null;
        }

        QueryWrapper<Company> qw = new QueryWrapper<>();
        qw.eq("organization_code", organizationCode).last("limit 1").orderByDesc("create_time");

        Company company = baseMapper.selectOne(qw);
        if (company != null) {
            return company;
        }
        return null;
    }


    @Override
    public Company getByUserId(Integer userId) {
        return baseMapper.selectOne(new QueryWrapper<Company>()
                .eq("user_id", userId)
                .last("limit 1")
                .orderByDesc("create_time")
        );
    }

    @Override
    public JsonResult verifyCompanyState(String state) {
        if (CompanyConstants.COMPANY_STATE_PASS.equals(state)) {
            return JsonResult.ok();
        }

        String str = CompanyConstants.labelState(state);
        return JsonResult.error("单位状态异常：" + str);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult registerCompany(CompanyFormVO companyFormVO) {
        if (companyFormVO == null) {
            throw new ParameterException("单位为空");
        }
        if (StrUtil.isBlank(companyFormVO.getUserName())) {
            throw new ParameterException("用户名为空");
        }

        RSA rsa = new RSA(Constants.RSA_PRIVATE_KEY, Constants.RSA_PUBLIC_KEY);

        byte[] decryptUsername = rsa.decrypt(companyFormVO.getUserName(), KeyType.PrivateKey);
        String username = StrUtil.str(decryptUsername, CharsetUtil.CHARSET_UTF_8);
        companyFormVO.setUserName(username);

        byte[] decryptPassword = rsa.decrypt(companyFormVO.getPassword(), KeyType.PrivateKey);
        String password = StrUtil.str(decryptPassword, CharsetUtil.CHARSET_UTF_8);
        companyFormVO.setPassword(password);

        Company company = new Company();
        BeanUtil.copyProperties(companyFormVO, company);
        company.setOrganizationCode(companyFormVO.getOrganizationCode().toUpperCase());
        company.setState(CompanyConstants.COMPANY_STATE_WAIT);

        if (company.getOrganizationCode().length() != CompanyConstants.CODE_CREDIT_LENGTH) {
            return JsonResult.error("社会统一信用代码为18位");
        }

        if (userService.getUserIsExistByUserName(company.getUserName())) {
            throw new BusinessException("账号已存在");
        }

        if (getUserIsExistByOrganizationCode(company.getOrganizationCode())) {
            throw new BusinessException("社会统一信用代码已存在");
        }

        // 设置用户账号
        User user = new User();
        user.setUsername(company.getUserName());
        user.setName(company.getName());
        // 账号有效
        user.setState(CompanyConstants.NO_FOUND_COMPANY);
        // 账号类型
        user.setUserType("3");
        user.setPassword(userService.encodePsw(company.getPassword()));
        // 默认未做问卷
        user.setCompanyQuestionnaire("1");

        if (userService.save(user)) {
            UserRole userRole = new UserRole();
            userRole.setRoleId(7);
            userRole.setUserId(user.getUserId());
            userRoleService.save(userRole);
            company.setUserId(user.getUserId());
            save(company);
            return JsonResult.ok("提交成功");
        }
        return JsonResult.error("提交失败");
    }

    @Override
    public JsonResult getDict() {
        Map<String, Object> map = new HashMap<>(16);
        //获取单位详情字典
        List<Dict> natureList = dictService.cacheNatureList(CompanyConstants.NATURE_LIST_TYPE);
        map.put("natureList", natureList);

        List<Dict> industryList = dictService.cacheList(CompanyConstants.INDUSTRY_LIST_TYPE);
        map.put("industryList", industryList);

        List<Dict> syszdList = dictService.cacheList(CompanyConstants.SYSZD_LIST_TYPE);
        map.put("syszdList", syszdList);

        List<Dict> levelList = dictService.cacheList(CompanyConstants.LEVEL_LIST_TYPE);
        map.put("levelList", levelList);

        List<Dict> scaleList = dictService.cacheList(CompanyConstants.SCALE_LIST_TYPE);
        map.put("scaleList", scaleList);

        List<Dict> hbIndustryList = dictService.cacheList(CompanyConstants.HB_INDUSTRY_LIST_TYPE);
        map.put("hbIndustryList", hbIndustryList);
        return JsonResult.ok().setData(map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult updateCompany(CompanyFormVO companyFormVO) {
        if (companyFormVO == null) {
            throw new ParameterException("单位为空");
        }

        Company company = baseMapper.selectById(companyFormVO.getId());
        if (company == null) {
            throw new BusinessException("单位不存在");
        }

        BeanUtil.copyProperties(companyFormVO, company);
        company.setState(CompanyConstants.COMPANY_STATE_WAIT);

        if (updateById(company)) {
            // 修改用户角色
            userRoleService.deleteRole(company.getUserId());
            UserRole userRole = new UserRole();
            userRole.setRoleId(7);
            userRole.setUserId(company.getUserId());
            userRoleService.save(userRole);

            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    @Override
    public boolean getUserIsExistByOrganizationCode(String organizationCode) {
        if (organizationCode != null && baseMapper.selectCount(new QueryWrapper<Company>()
                .eq("organization_code", organizationCode.toUpperCase())) > 0) {
            return true;
        }
        return false;
    }

    @Override
    public boolean isCreditCode(String organizationCode) {
        if (StrUtil.isBlank(organizationCode)) {
            return false;
        }
        // 组织机构代码
//        if (organizationCode.length() == 9) {
//            return RegexUtil.isOrganizationCertificate(organizationCode);
//        }
        // 社会统一信用代码
        if (organizationCode.length() == 18) {
            return CreditCodeUtil.isCreditCode(organizationCode);
        }
        return false;
    }

    @Override
    public JsonResult detailCompany(Integer userId) {
        if (userId == null) {
            throw new ParameterException("用户编号为空");
        }

        Company company = baseMapper.selectOne(new QueryWrapper<Company>().eq("user_id", userId).last("limit 1").orderByDesc("create_time"));
        if (company == null) {
            throw new BusinessException("用户编号为空");
        }

        String businessUrl = company.getBusinessUrl();
        String businessUrlPreview = minioService.getPreSignedObjectUrl(MinioBucket.MINIO_COMPANY, businessUrl);
        company.setBusinessUrlPreview(businessUrlPreview);

        String legalPersons = company.getLegalPersons();
        String legalPersonsPreview = minioService.getPreSignedObjectUrl(MinioBucket.MINIO_COMPANY, legalPersons);
        company.setLegalPersonsPreview(legalPersonsPreview);
        return JsonResult.ok().setData(getDetail(company));
    }

    @Override
    public JsonResult countCompany(PageParam<CompanyListVO> page) {
        //申请时间
        page = (PageParam<CompanyListVO>) CompanyUtil.putApplyTime(page);
        page.getPageData().put("state", CompanyConstants.COMPANY_STATE_PASS);
        page.setSearchCount(false);
        page.setSize(100);
        Map<String, Object> map = new HashMap<>(5);
        Integer total = baseMapper.countTotal(page);
        List<Map<String, Object>> provinceList = baseMapper.countProvince(page);
        List<Map<String, Object>> natureList = baseMapper.countNature(page);
        List<Map<String, Object>> industryList = baseMapper.countIndustry(page);
        List<Map<String, Object>> scaleList = baseMapper.countScale(page);
        map.put("total", total);
        map.put("provinceList", provinceList);
        map.put("natureList", natureList);
        map.put("industryList", industryList);
        map.put("scaleList", scaleList);
        return JsonResult.ok().setData(map);
    }

    @Override
    public JsonResult getStatisticsDict() {
        Map<String, Object> map = new HashMap<>(3);
        //获取单位详情字典
        List<Dict> natureList = dictService.cacheList(CompanyConstants.NATURE_LIST_TYPE);
        map.put("natureList", natureList);

        List<Dict> industryList = dictService.cacheList(CompanyConstants.INDUSTRY_LIST_TYPE);
        map.put("industryList", industryList);

        List<Dict> scaleList = dictService.cacheList(CompanyConstants.SCALE_LIST_TYPE);
        map.put("scaleList", scaleList);
        return JsonResult.ok().setData(map);
    }

    @Override

    public JsonResult forgotCompany(CompanyForgotFormVO companyForgotFormVO) {
        List<Company> list = baseMapper.selectList(new QueryWrapper<Company>().eq("organization_code", companyForgotFormVO.getOrganizationCode()));

        List<User> users = userService.list(new QueryWrapper<User>().eq("username", companyForgotFormVO.getEmail()));

        if (list.isEmpty() || list.size() == 0) {
            return JsonResult.error("密码找回失败，没有查询到单位注册社会统一信用代码");
        }
        if (users.isEmpty() || users.size() == 0) {
            return JsonResult.error("密码找回失败，没有查询到单位注册邮箱");
        }
        if (!list.get(0).getUserId().equals(users.get(0).getUserId())) {
            return JsonResult.error("密码找回失败，没有查询到单位注册信息");
        }
        String password = RandomUtil.randomString(CompanyConstants.COMPANY_RANDOM_WORD, 1).toUpperCase() + RandomUtil.randomNumbers(6);
        User user = new User();
        user.setPassword(userService.encodePsw(password));
        user.setUserId(list.get(0).getUserId());
        if (userService.updateById(user)) {
            String[] emails = {companyForgotFormVO.getEmail()};
            log.info(password);
            emailService.sendTextEmail("密码找回", "您的单位密码：" + password, emails);
            OperRecord operRecord = new OperRecord();
            operRecord.setModel("密码找回");
            operRecord.setDescription(list.get(0).getName());
            operRecord.setResult(password);
            operRecord.setParam(companyForgotFormVO.getEmail());
            operRecordService.save(operRecord);
            return JsonResult.ok("密码找回成功");
        }
        return JsonResult.error("密码找回失败");
    }

    /**
     * 检查单位是否存在
     *
     * @param id 单位编号
     * @return Company 单位
     */
    private Company verifyCompany(Integer id) {
        if (id == null) {
            throw new ParameterException("单位编号为空");
        }

        Company company = baseMapper.selectById(id);
        if (company == null) {
            throw new BusinessException("单位不存在");
        }
        return company;
    }

    /**
     * 获取数据字典
     *
     * @param company 单位
     * @return CompanyFormVO 单位表单
     */
    private CompanyFormVO getDetail(Company company) {
        CompanyFormVO companyFormVO = new CompanyFormVO();
        BeanUtil.copyProperties(company, companyFormVO);

        //获取单位详情字典
        List<Dict> natureList = dictService.cacheNatureList(CompanyConstants.NATURE_LIST_TYPE);

        companyFormVO.setNatureDictList(natureList);

        List<Dict> industryList = dictService.cacheList(CompanyConstants.INDUSTRY_LIST_TYPE);
        companyFormVO.setIndustryDictList(industryList);

        List<Dict> syszdList = dictService.cacheList(CompanyConstants.SYSZD_LIST_TYPE);
        companyFormVO.setSyszdDictList(syszdList);

        List<Dict> levelList = dictService.cacheList(CompanyConstants.LEVEL_LIST_TYPE);
        companyFormVO.setLevelDictList(levelList);

        List<Dict> scaleList = dictService.cacheList(CompanyConstants.SCALE_LIST_TYPE);
        companyFormVO.setScaleDictList(scaleList);

        List<Dict> hbIndustryList = dictService.cacheList(CompanyConstants.HB_INDUSTRY_LIST_TYPE);
        companyFormVO.setHbIndustryList(hbIndustryList);

        return companyFormVO;
    }

    @Override
    public List<Company> listCooperative() {
        QueryWrapper<Company> qw = new QueryWrapper<>();
        qw.select("id, CONCAT(`name`,'(',organization_code,')') AS name")
                .eq("state", CompanyConstants.COMPANY_STATE_PASS)
                .eq("cooperative", CompanyConstants.COOPERATIVE_YES)
                .orderByDesc("create_time");
        return baseMapper.selectList(qw);
    }

    @Override
    public JsonResult getCompanyByPartOrganizationCode(String organizationCode) {
        List<Company> companies =  baseMapper.getCompanyByOrganizationCode(organizationCode);

        // 去掉网签单位性质
        List<String> natures = companies.stream().map(Company::getNature).filter(d -> Integer.parseInt(d)<70).collect(Collectors.toList());
        List<String> industries = companies.stream().map(Company::getIndustry).collect(Collectors.toList());
        List<String> companyLevels = companies.stream().map(Company::getCompanyLevel).collect(Collectors.toList());
        List<String> hbIndustries = companies.stream().map(Company::getHbIndustry).collect(Collectors.toList());
        Map<String,Dict> natureMap = commonRefService.refDict(natures,CompanyConstants.NATURE_LIST_TYPE);
        Map<String,Dict> industryMap = commonRefService.refDict(industries,CompanyConstants.INDUSTRY_LIST_TYPE);
        Map<String,Dict> companyLevelMap = commonRefService.refDict(companyLevels,CompanyConstants.LEVEL_LIST_TYPE);
        Map<String,Dict> hbIndustryMap = commonRefService.refDict(hbIndustries,CompanyConstants.HB_INDUSTRY_LIST_TYPE);

        List<CompanyFromCodeVo> companyFromCodeVos = new ArrayList<>();
        for (Company company : companies) {
            CompanyFromCodeVo companyFromCodeVo = new CompanyFromCodeVo();
            BeanUtil.copyProperties(company, companyFromCodeVo);
            if (StrUtil.isNotBlank(company.getNature())) {
                companyFromCodeVo.setNatureContent(natureMap.get(company.getNature()).getLabel());
            }
            if (StrUtil.isNotBlank(company.getIndustry())) {
                companyFromCodeVo.setIndustryContent(industryMap.get(company.getIndustry()).getLabel());
            }
            if (StrUtil.isNotBlank(company.getCompanyLevel())){
                companyFromCodeVo.setCompanyLevelContent(companyLevelMap.get(company.getCompanyLevel()).getLabel());
            }
            if (StrUtil.isNotBlank(company.getHbIndustry())) {
                companyFromCodeVo.setHbIndustryContent(hbIndustryMap.get(company.getHbIndustry()).getLabel());
            }
            companyFromCodeVos.add(companyFromCodeVo);
        }

        return JsonResult.ok().setData(companyFromCodeVos);
    }
}